﻿using System.Data;
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Drawing.Charts;
using Style = DocumentFormat.OpenXml.Office2010.Drawing.Charts.Style;

namespace OpenXmlEasy.Basic
{
    internal static class ChartBasic
    {
        /// <summary>
        /// 在ChartPart中插入一个Bar图表
        /// </summary>
        /// <param name="part"></param>
        /// <param name="categoryColumn"></param>
        /// <param name="seriesColumnIndexs"></param>
        /// <param name="chartType"></param>
        public static void GenerateChartSpace(this ChartPart part, ChartType chartType, DataColumn categoryColumn,
           params int[] seriesColumnIndexs)
        {
            part.GenerateEmbeddedPackagePart();

            var table = categoryColumn.Table;
            var categoryIndex = table.Columns.IndexOf(categoryColumn);
            var seriesColumns = seriesColumnIndexs.Select(t => table.Columns[t]).ToList();

            var chartSpace = new ChartSpace();
            chartSpace.AddNamespaceDeclaration("c", "http://schemas.openxmlformats.org/drawingml/2006/chart");
            chartSpace.AddNamespaceDeclaration("a", "http://schemas.openxmlformats.org/drawingml/2006/main");
            chartSpace.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
            var date1904 = new Date1904 { Val = false };
            var editingLanguage = new EditingLanguage { Val = "zh-CN" };
            var roundedCorners = new RoundedCorners { Val = false };

            var alternateContent = new AlternateContent();
            alternateContent.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");

            var alternateContentChoice = new AlternateContentChoice { Requires = "c14" };
            alternateContentChoice.AddNamespaceDeclaration("c14", "http://schemas.microsoft.com/office/drawing/2007/8/2/chart");
            var style1 = new Style { Val = 102 };

            alternateContentChoice.AppendChild(style1);

            var alternateContentFallback = new AlternateContentFallback();
            var style2 = new DocumentFormat.OpenXml.Drawing.Charts.Style { Val = 2 };

            alternateContentFallback.AppendChild(style2);

            alternateContent.AppendChild(alternateContentChoice);
            alternateContent.AppendChild(alternateContentFallback);

            var chart = new Chart();
            var autoTitleDeleted = new AutoTitleDeleted { Val = false };

            var plotArea = new PlotArea();
            var layout = new Layout();
            OpenXmlCompositeElement myChart = null;
            if (chartType.Equals(ChartType.Bar) || chartType.Equals(ChartType.Column))
            {
                myChart = new BarChart();
            }
            else if (chartType.Equals(ChartType.Line))
            {
                myChart = new LineChart();
            }
            else if (chartType.Equals(ChartType.Radar))
            {
                myChart = new RadarChart();
            }
            else if (chartType.Equals(ChartType.Pie))
            {
                myChart = new PieChart();
            }
            if (myChart == null) return;

            #region Data

            System.UInt32 seriesId = 0U;
            foreach (var seriesColumn in seriesColumns)
            {
                OpenXmlCompositeElement myChartSeries = null;
                if (chartType.Equals(ChartType.Bar) || chartType.Equals(ChartType.Column))
                {
                    myChartSeries = new BarChartSeries();
                }
                else if (chartType.Equals(ChartType.Line))
                {
                    myChartSeries = new LineChartSeries();
                }
                else if (chartType.Equals(ChartType.Radar))
                {
                    myChartSeries = new RadarChartSeries();
                }
                else if (chartType.Equals(ChartType.Pie))
                {
                    myChartSeries = new PieChartSeries();
                }
                if (myChartSeries == null) return;

                var index1 = new Index { Val = seriesId };
                var order1 = new Order { Val = seriesId };

                var seriesText1 = new SeriesText();

                var stringReference1 = new StringReference();

                var stringCache1 = new StringCache();
                var pointCount1 = new PointCount { Val = 1U };

                var stringPoint1 = new StringPoint { Index = 0U };
                var numericValue1 = new NumericValue { Text = seriesColumn.ColumnName };

                stringPoint1.AppendChild(numericValue1);

                stringCache1.AppendChild(pointCount1);
                stringCache1.AppendChild(stringPoint1);

                stringReference1.AppendChild(stringCache1);

                seriesText1.AppendChild(stringReference1);
                var invertIfNegative1 = new InvertIfNegative { Val = false };

                var categoryAxisData1 = new CategoryAxisData();

                var stringReference2 = new StringReference();

                var stringCache2 = new StringCache();
                var pointCount2 = new PointCount { Val = 4U };
                var categoryId = 0U;
                foreach (DataRow row in table.Rows)
                {
                    var categoryName = row[categoryIndex].ToString();

                    var stringPoint2 = new StringPoint { Index = categoryId++ };
                    var numericValue2 = new NumericValue { Text = categoryName };

                    stringPoint2.AppendChild(numericValue2);

                    stringCache2.AppendChild(stringPoint2);
                }

                stringCache2.AppendChild(pointCount2);

                stringReference2.AppendChild(stringCache2);

                categoryAxisData1.AppendChild(stringReference2);

                var values1 = new Values();

                var numberReference1 = new NumberReference();

                var numberingCache1 = new NumberingCache();
                var formatCode1 = new FormatCode { Text = "General" };
                var pointCount3 = new PointCount { Val = 4U };
                categoryId = 0U;
                foreach (DataRow row in table.Rows)
                {
                    var value = row[table.Columns.IndexOf(seriesColumn)].ToString();

                    var numericPoint1 = new NumericPoint { Index = categoryId++ };
                    var numericValue6 = new NumericValue { Text = value };

                    numericPoint1.AppendChild(numericValue6);

                    numberingCache1.AppendChild(numericPoint1);
                }

                numberingCache1.AppendChild(formatCode1);
                numberingCache1.AppendChild(pointCount3);

                numberReference1.AppendChild(numberingCache1);

                values1.AppendChild(numberReference1);

                myChartSeries.AppendChild(index1);
                myChartSeries.AppendChild(order1);
                myChartSeries.AppendChild(seriesText1);
                myChartSeries.AppendChild(invertIfNegative1);
                myChartSeries.AppendChild(categoryAxisData1);
                myChartSeries.AppendChild(values1);

                myChart.AppendChild(myChartSeries);
                seriesId++;
            }
            #endregion

            var dataLabels1 = new DataLabels();
            var showLegendKey1 = new ShowLegendKey { Val = false };
            var showValue1 = new ShowValue { Val = false };
            var showCategoryName1 = new ShowCategoryName { Val = false };
            var showSeriesName1 = new ShowSeriesName { Val = false };
            var showPercent1 = new ShowPercent { Val = false };
            var showBubbleSize1 = new ShowBubbleSize { Val = false };

            dataLabels1.AppendChild(showLegendKey1);
            dataLabels1.AppendChild(showValue1);
            dataLabels1.AppendChild(showCategoryName1);
            dataLabels1.AppendChild(showSeriesName1);
            dataLabels1.AppendChild(showPercent1);
            dataLabels1.AppendChild(showBubbleSize1);
            var gapWidth1 = new GapWidth { Val = (UInt16Value)150U };
            var axisId1 = new AxisId { Val = 192672896U };
            var axisId2 = new AxisId { Val = 192674432U };

            var varyColors = new VaryColors { Val = false };

            if (chartType.Equals(ChartType.Bar) || chartType.Equals(ChartType.Column))
            {
                var barDirection = new BarDirection { Val = chartType.Equals(ChartType.Bar) ? BarDirectionValues.Bar : BarDirectionValues.Column };

                //barChart1.AppendChild(barGrouping1);
                myChart.AppendChild(barDirection);
            }
            else if (chartType.Equals(ChartType.Radar))
            {
                var radarStyle = new RadarStyle { Val = RadarStyleValues.Marker };
                myChart.AppendChild(radarStyle);
            }
            else if (chartType.Equals(ChartType.Pie))
            {
                varyColors.Val = true;
            }

            myChart.AppendChild(varyColors);
            myChart.AppendChild(dataLabels1);
            myChart.AppendChild(gapWidth1);
            myChart.AppendChild(axisId1);
            myChart.AppendChild(axisId2);

            var categoryAxis1 = new CategoryAxis();
            var axisId3 = new AxisId { Val = 192672896U };

            var scaling1 = new Scaling();
            var orientation1 = new Orientation { Val = OrientationValues.MinMax };

            scaling1.AppendChild(orientation1);
            var delete1 = new Delete { Val = false };
            var axisPosition1 = new AxisPosition { Val = AxisPositionValues.Bottom };
            var majorTickMark1 = new MajorTickMark { Val = TickMarkValues.Outside };
            var minorTickMark1 = new MinorTickMark { Val = TickMarkValues.None };
            var tickLabelPosition1 = new TickLabelPosition { Val = TickLabelPositionValues.NextTo };
            var crossingAxis1 = new CrossingAxis { Val = 192674432U };
            var crosses1 = new Crosses { Val = CrossesValues.AutoZero };
            var autoLabeled1 = new AutoLabeled { Val = true };
            var labelAlignment1 = new LabelAlignment { Val = LabelAlignmentValues.Center };
            var labelOffset1 = new LabelOffset { Val = (UInt16Value)100U };
            var noMultiLevelLabels1 = new NoMultiLevelLabels { Val = false };

            categoryAxis1.AppendChild(axisId3);
            categoryAxis1.AppendChild(scaling1);
            categoryAxis1.AppendChild(delete1);
            categoryAxis1.AppendChild(axisPosition1);
            categoryAxis1.AppendChild(majorTickMark1);
            categoryAxis1.AppendChild(minorTickMark1);
            categoryAxis1.AppendChild(tickLabelPosition1);
            categoryAxis1.AppendChild(crossingAxis1);
            categoryAxis1.AppendChild(crosses1);
            categoryAxis1.AppendChild(autoLabeled1);
            categoryAxis1.AppendChild(labelAlignment1);
            categoryAxis1.AppendChild(labelOffset1);
            categoryAxis1.AppendChild(noMultiLevelLabels1);

            var valueAxis1 = new ValueAxis();
            var axisId4 = new AxisId { Val = 192674432U };

            var scaling2 = new Scaling();
            var orientation2 = new Orientation { Val = OrientationValues.MinMax };

            scaling2.AppendChild(orientation2);
            var delete2 = new Delete { Val = false };
            var axisPosition2 = new AxisPosition { Val = AxisPositionValues.Left };
            var majorGridlines1 = new MajorGridlines();
            var numberingFormat1 = new NumberingFormat { FormatCode = "General", SourceLinked = true };
            var majorTickMark2 = new MajorTickMark { Val = TickMarkValues.Outside };
            var minorTickMark2 = new MinorTickMark { Val = TickMarkValues.None };
            var tickLabelPosition2 = new TickLabelPosition { Val = TickLabelPositionValues.NextTo };
            var crossingAxis2 = new CrossingAxis { Val = 192672896U };
            var crosses2 = new Crosses { Val = CrossesValues.AutoZero };
            var crossBetween1 = new CrossBetween { Val = CrossBetweenValues.Between };

            valueAxis1.AppendChild(axisId4);
            valueAxis1.AppendChild(scaling2);
            valueAxis1.AppendChild(delete2);
            valueAxis1.AppendChild(axisPosition2);
            valueAxis1.AppendChild(majorGridlines1);
            valueAxis1.AppendChild(numberingFormat1);
            valueAxis1.AppendChild(majorTickMark2);
            valueAxis1.AppendChild(minorTickMark2);
            valueAxis1.AppendChild(tickLabelPosition2);
            valueAxis1.AppendChild(crossingAxis2);
            valueAxis1.AppendChild(crosses2);
            valueAxis1.AppendChild(crossBetween1);

            plotArea.AppendChild(layout);
            plotArea.AppendChild(myChart);
            plotArea.AppendChild(categoryAxis1);
            plotArea.AppendChild(valueAxis1);

            var legend1 = new Legend();
            var legendPosition1 = new LegendPosition { Val = LegendPositionValues.Right };
            var overlay1 = new Overlay { Val = false };

            legend1.AppendChild(legendPosition1);
            legend1.AppendChild(overlay1);
            var plotVisibleOnly1 = new PlotVisibleOnly { Val = true };
            var displayBlanksAs1 = new DisplayBlanksAs { Val = DisplayBlanksAsValues.Gap };
            var showDataLabelsOverMaximum1 = new ShowDataLabelsOverMaximum { Val = false };

            chart.AppendChild(autoTitleDeleted);
            chart.AppendChild(plotArea);
            chart.AppendChild(legend1);
            chart.AppendChild(plotVisibleOnly1);
            chart.AppendChild(displayBlanksAs1);
            chart.AppendChild(showDataLabelsOverMaximum1);

            var externalData1 = new ExternalData { Id = "rId1" };
            var autoUpdate1 = new AutoUpdate { Val = false };

            externalData1.AppendChild(autoUpdate1);

            chartSpace.AppendChild(date1904);
            chartSpace.AppendChild(editingLanguage);
            chartSpace.AppendChild(roundedCorners);
            chartSpace.AppendChild(alternateContent);
            chartSpace.AppendChild(chart);
            chartSpace.AppendChild(externalData1);

            part.ChartSpace = chartSpace;

        }

        #region Binary Data

        private static void GenerateEmbeddedPackagePart(this ChartPart part)
        {
            var embeddedPackagePart1 = part.AddNewPart<EmbeddedPackagePart>("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "rId1");
            System.IO.Stream data = GetBinaryDataStream(EmbeddedPackagePart1Data);
            embeddedPackagePart1.FeedData(data);
            data.Close();
        }

        private const string EmbeddedPackagePart1Data = "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";

        private static System.IO.Stream GetBinaryDataStream(string base64String)
        {
            return new System.IO.MemoryStream(System.Convert.FromBase64String(base64String));
        }

        #endregion


        public static void InsertLine(DataColumn categoryColumn, DataColumn[] dataColumns, string yAxisTitle)
        {

        }

    }
}
